`timescale 1ns/1ns
`default_nettype none
/*
* - 处理读背光数据ram的地址
* - 处理背光数据写进display_buf的地址
*/
module pixel_reader_mbi6334
    #(
    parameter   DW      = 1
    )
    (
    //systen signal
    input  wire         I_sclk,
    input  wire         I_rst_n,
    //input  wire         vs,
    //config
    output wire         O_read_busy,        // 读忙碌
    //read request
    input  wire         I_read_req,         // 读请求
    input  wire [5:0]   I_read_chip_id  ,   // 读第几芯片
    input  wire [5:0]   I_read_chip_max ,   // 读芯片最大数
    input  wire [5:0]   I_read_scan_id  ,      // 读第几扫
    input  wire [5:0]   I_read_scan_max ,      // 最在扫数
    input  wire [5:0]   I_read_port_max ,      // 读最大port数
    input  wire [5:0]   I_read_pin_id   ,      // 读芯片的每几个引脚
    input  wire [5:0]   I_read_pin_max  ,      // 读多少个芯片引脚
    
    input  wire         I_read_buf_index,      // 乒乓操作
    //back_ram interface
    output wire         O_back_ram_en,
    output wire [13:0]  O_back_ram_addr,
    input  wire [15:0]  I_back_data,
    // ram interface
    output wire         O_ram_wclk,
    output reg  [DW-1:0]O_ram_wren,         // 每bit控制一个ram块，一共8个ram块
    output reg  [9:0]   O_ram_addr,         // 第9位 乒乓操作  8:0 512个像素
    output reg  [15:0]  O_ram_data
    );

//rgb串行
// `ifdef CFG_RGB 
// localparam [2:0]cfg_rgb_sel    = 2'b2;
// localparam [2:0]cfg_rgb_data   = 2'b3;
// `else
localparam [2:0]cfg_rgb_sel    = 2'b0;
localparam [2:0]cfg_rgb_data   = 2'b1;
// `endif

localparam [2:0]
    IDLE    = 0,
    REQ_MUX = 1,
    READ    = 2,
    LOOP    = 3,
    DONE    = 4;

localparam
    RL = 7;

reg   [2:0]  state;
reg   [2:0]  next;
reg   [3:0]  start_sr;
reg   [RL:0] read_sr;

reg         busy;
reg  [1:0]  end_sr;
reg         req_sr;
reg  [2:0]  done_sr;

reg  [5:0]  read_port_max;
reg  [5:0]  read_pin_id;
reg  [5:0]  read_pin_id_start;
reg  [5:0]  read_pin_id_max;  //读多少个引脚

reg  [5:0]  read_chip_id;
reg  [5:0]  read_chip_id_max; //读多少个芯片
reg  [5:0]  read_chip_id_start;

reg         read_buf_index;

reg  [5:0]  read_scan_id;
reg  [5:0]  read_scan_max;
reg  [5:0]  read_scan_id_start;

reg  [5:0]  read_pin_id_add;


reg  [5:0]  read_port_id;
// reg  [3:0]  port_id_max;


reg  [5:0]  h_block;
reg  [6:0]  l_block;
reg  [5:0]  h_block_t;
reg  [6:0]  l_block_t;
reg  [5:0]  chip_id_tmp1;
reg  [5:0]  chip_id_tmp2;
reg  [5:0]  chip_id_tmp3;
reg  [5:0]  chip_id_tmp4;
reg  [5:0]  chip_id_tmp5;

reg  [5:0]  port_id_tmp1;
reg  [5:0]  port_id_tmp2;
reg  [5:0]  port_id_tmp3;
reg  [5:0]  port_id_tmp4;
reg  [5:0]  port_id_tmp5;

reg  [9:0]  ram_addr      ;
reg  [9:0]  ram_addr_tmp1 ;
reg  [9:0]  ram_addr_tmp2 ;
reg  [9:0]  ram_addr_tmp3 ;
reg  [9:0]  ram_addr_tmp4 ;
reg  [9:0]  ram_addr_tmp5 ;

reg  [1:0]  read_chip_rgb      ;

wire  [15:0]  d1;
wire  [15:0]  d;

reg [5:0] h_chip;
reg [6:0] l_chip;
reg [5:0] h_pin;
reg [6:0] l_pin;
reg [5:0] h_scan;
reg [6:0] l_scan;
reg [5:0] h_port;
reg [6:0] l_port;
//------------------------Body---------------------------
//{{{+++++++++++++++++++++fsm++++++++++++++++++++++++++++
// state
always @(posedge I_sclk or negedge I_rst_n) begin
    if (!I_rst_n)
        state <= IDLE;
    else
        state <= next;
end

// next
always @(*) begin
    case (state)
        IDLE: begin
            if(start_sr[3])
                next = REQ_MUX;
            else 
                next = IDLE;
        end

        REQ_MUX: begin
            next = READ;
        end

        READ: begin
            // if (read_chip_id == read_chip_id_max && read_chip_rgb == cfg_rgb_sel )
            // if (read_chip_id == read_chip_id_max && read_pin_id == read_pin_id_max  )
            // if (read_pin_id == read_pin_id_max  ) //mbi6322 一次读一行，32个像素
            if (read_scan_id == read_scan_max && read_pin_id == read_pin_id_max  )//mbi6334一次读一个芯片512个像素 8扫x64
                next = LOOP;
            else
                next = READ;
        end
        
        LOOP:begin
            if(read_port_id==read_port_max) 
                next = DONE;
            else 
                next = READ;
        end

        DONE: begin
            next = IDLE;
        end

        default: begin
            next = IDLE;
        end
    endcase
end

//}}}++++++++++++++++++++++++++++++++++++++++++++++++++++

//{{{++++++++++++++++++++++++++++++++++++++++++++++++++++
//O_read_busy
assign O_read_busy = busy;
//busy
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        busy <= 'b0;
    else if(!busy && I_read_req)
        busy <= 1'b1;
    else if(done_sr[2:1]==2'b01)
        busy <= 'b0;

//req_sr
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        req_sr <= 'b0;
    else if(!busy && I_read_req)
        req_sr <= 1'b1;
    else
        req_sr <= 'b0;

//done_sr[2:0]
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        done_sr <= 'b0;
    else
        done_sr <= {done_sr[1:0],end_sr[1]};

//end_sr[1:0]
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        end_sr <= 'b0;
    else if(state==DONE && next==IDLE)
        end_sr <= 2'b11;
    else
        end_sr <= end_sr << 1;

//command buffer
always@(posedge I_sclk)
    if(!busy && I_read_req)
    begin
        read_port_max       <= I_read_port_max;
        
        read_pin_id_start   <= I_read_pin_id ;  //I_read_pin_id * cfg_rgb_data;  //rgb串行，只点一种颜色，
        read_pin_id_max     <= I_read_pin_max;       //读多少个pin
        
        read_chip_id_start  <= I_read_chip_id;
        read_chip_id_max    <= I_read_chip_max;     //读多少个芯片
        
        read_buf_index      <= I_read_buf_index;

        read_scan_id_start  <= I_read_scan_id;
        read_scan_max       <= I_read_scan_max;
    end

//start_sr[3:0]
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        start_sr <= 'b0;
    else if((!busy && I_read_req) || req_sr)
        start_sr <= {start_sr[2:0], 1'b1};
    else
        start_sr <= {start_sr[2:0], 1'b0};

//read_sr[RL:0]
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        read_sr <= 'b0;
    else if(state == READ)
        read_sr <= {read_sr[RL-1:0],1'b1};
    else
        read_sr <= {read_sr[RL-1:0],1'b0};

//read_chip_id[4:0]
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        read_chip_id <= 'b0;
    else if(!busy && I_read_req)
        read_chip_id <= I_read_chip_id;

//pin_id
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        read_pin_id <= 'b0;
    else if(state==IDLE || state == LOOP)
        // read_pin_id <= read_pin_id_start;
        read_pin_id <= 'b0;
    else if(state == READ)
    begin
        if(read_pin_id == read_pin_id_max)
            read_pin_id <= 'd0;
        else 
            read_pin_id <= read_pin_id + 1'b1;
    end    
//scan
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        read_scan_id <= 'b0;
    else if(state==IDLE )
        read_scan_id <= 'b0;
    else if(state == READ)
    begin
        if(read_pin_id == read_pin_id_max)
            read_scan_id <= read_scan_id + 1'b1;
    end 
//read_port_id[4:0]
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        read_port_id <= 'b0;
    else if(state==IDLE)
        read_port_id <= 'b0;
    else if(state == LOOP)
        read_port_id <= read_port_id + 1'b1;
//read_chip_rgb[1:0]
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        read_chip_rgb <= 'b0;
    else if(state==IDLE || state == LOOP)
        read_chip_rgb <= 'b0;
    else if(state == READ )begin
        if( read_chip_rgb== cfg_rgb_sel)
            read_chip_rgb <= 'b0;
        else
            read_chip_rgb <= read_chip_rgb + 1'b1;
    end
    
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        read_pin_id_add <= 'b0;
    else
        // read_pin_id_add <= read_chip_rgb + read_pin_id;
        read_pin_id_add <= read_pin_id;
//}}}++++++++++++++++++++++++++++++++++++++++++++++++++++

//{{{++++++++++++++++++++++++back_part_ram++++++++++++++++++++
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n) 
        h_block_t <= 'b0;
    else 
        h_block_t <= h_chip + h_scan + h_port;
        // h_block_t <= h_chip + h_scan ;
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        l_block_t <= 'b0;
    else
        l_block_t <= l_chip + l_scan + l_port;
        // l_block_t <= l_chip + l_scan ;
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n) 
        h_block <= 'b0;
    else 
        h_block <= h_block_t + h_pin;
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        l_block <= 'b0;
    else
        l_block <= l_block_t + l_pin;

        
assign O_back_ram_en   = read_sr[2];
assign O_back_ram_addr[12:0] = {h_block[5:0],l_block[6:0]};
assign O_back_ram_addr[13]  = 1'b0;
//}}}++++++++++++++++++++++++++++++++++++++++++++++++++++

//{{{+++++++++++++++++ram interface +++++++++++++++++++++
//像素重排序

//ram_rdata_adj[15:0] 对16bit重排序
assign d = I_back_data[15:0];
assign d1 = {d[0],d[1],d[2], d[3], d[4] ,d[5] ,d[6] ,d[7] ,
             d[8],d[9],d[10],d[11],d[12],d[13],d[14],d[15]};

//O_ram_wclk
assign O_ram_wclk = I_sclk;
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        O_ram_wren <= 'b0;
    else if(read_sr[2])
    begin
        O_ram_wren <= (1'b1 << port_id_tmp3[2:0]);
        //case(port_id_tmp3[2:0])
        //3'b000:O_ram_wren<= 6'b00_0001;
        //3'b001:O_ram_wren<= 6'b00_0010;
        //3'b010:O_ram_wren<= 6'b00_0100;
        //3'b011:O_ram_wren<= 6'b00_1000;
        //3'b100:O_ram_wren<= 6'b01_0000;
        //3'b101:O_ram_wren<= 6'b10_0000;
        //3'b110:O_ram_wren<= 6'b00_0000;
        //3'b111:O_ram_wren<= 6'b00_0000;
        //endcase
    end
    else
        O_ram_wren <= 'b0;
// always@(posedge I_sclk or negedge I_rst_n)
    // if(!I_rst_n)
        // O_ram_data <= 'b0;
    // else if(read_sr[2])
        // O_ram_data <= d1;

always@(*)
        O_ram_data <= d1;
                      
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n) 
        O_ram_addr[9] <= 'b0;
    else if(read_sr[2])
        O_ram_addr[9] <= read_buf_index;

always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        O_ram_addr[8:0] <= 'b0;
    else 
        O_ram_addr[8:0] <= ram_addr_tmp3[8:0];
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
        ram_addr[8:0] <= 'b0;
    else if(state == REQ_MUX || state ==LOOP)
        ram_addr[8:0] <= 'b0;
    else if(state == READ)
        ram_addr[8:0] <= ram_addr[8:0] + 1'b1;
always@(posedge I_sclk )
    begin
        ram_addr_tmp1 <= {1'd0,ram_addr[8:0]};
        ram_addr_tmp2 <= ram_addr_tmp1;
        ram_addr_tmp3 <= ram_addr_tmp2;
        ram_addr_tmp4 <= ram_addr_tmp3;
        ram_addr_tmp5 <= ram_addr_tmp4;
    end
//分布很有规律
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n) begin
         h_chip <= 'd0;
         l_chip <= 'd0;
    end
    else begin
           case (read_chip_id)
              0: begin
                   h_chip <= 'd0;
                   l_chip <= 'd0;
                 end
              1: begin
                   h_chip <= 'd14;
                   l_chip <= 'd0;
                 end
              2: begin
                   h_chip <= 'd28;
                   l_chip <= 'd0;
                 end
              3: begin
                   h_chip <= 'd21;
                   l_chip <= 'd0;
                 end
              4: begin
                   h_chip <= 'd7;
                   l_chip <= 'd0;
                 end
              default:  begin
                   h_chip <= 'd0;
                   l_chip <= 'd0;
                 end
            endcase
    end
//每个引脚所在位置    
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n) begin
         h_pin <= 'd0;
    end
    else case (read_pin_id_add)
              0 : h_pin <= 'd0  ;
              1 : h_pin <= 'd0  ;
              2 : h_pin <= 'd0  ;
              3 : h_pin <= 'd0  ;
              4 : h_pin <= 'd0  ;
              5 : h_pin <= 'd0  ;
              6 : h_pin <= 'd0  ;
              7 : h_pin <= 'd0  ;
              8 : h_pin <= 'd0  ;
              9 : h_pin <= 'd0  ;
              10: h_pin <= 'd0  ;
              11: h_pin <= 'd0  ;
              12: h_pin <= 'd0  ;
              13: h_pin <= 'd0  ;
              14: h_pin <= 'd0  ;
              15: h_pin <= 'd0  ;
              16: h_pin <= 'd0  ;
              17: h_pin <= 'd0  ;
              18: h_pin <= 'd0  ;
              19: h_pin <= 'd0  ;
              20: h_pin <= 'd0  ;
              21: h_pin <= 'd0  ;
              22: h_pin <= 'd0  ;
              23: h_pin <= 'd0  ;
              24: h_pin <= 'd0  ;
              25: h_pin <= 'd0  ;
              26: h_pin <= 'd0  ;
              27: h_pin <= 'd0  ;
              28: h_pin <= 'd0  ;
              29: h_pin <= 'd0  ;
              30: h_pin <= 'd0  ;
              31: h_pin <= 'd0  ;
              32: h_pin <= 'd0  ;
              33: h_pin <= 'd0  ;
              34: h_pin <= 'd0  ;
              35: h_pin <= 'd0  ;
              36: h_pin <= 'd0  ;
              37: h_pin <= 'd0  ;
              38: h_pin <= 'd0  ;
              39: h_pin <= 'd0  ;
              40: h_pin <= 'd0  ;
              41: h_pin <= 'd0  ;
              42: h_pin <= 'd0  ;
              43: h_pin <= 'd0  ;
              44: h_pin <= 'd0  ;
              45: h_pin <= 'd0  ;
              46: h_pin <= 'd0  ;
              47: h_pin <= 'd0  ;
              48: h_pin <= 'd0  ;
              49: h_pin <= 'd0  ;
              50: h_pin <= 'd0  ;
              51: h_pin <= 'd0  ;
              52: h_pin <= 'd0  ;
              53: h_pin <= 'd0  ;
              54: h_pin <= 'd0  ;
              55: h_pin <= 'd0  ;
              56: h_pin <= 'd0  ;
              57: h_pin <= 'd0  ;
              58: h_pin <= 'd0  ;
              59: h_pin <= 'd0  ;
              60: h_pin <= 'd0  ;
              61: h_pin <= 'd0  ;
              62: h_pin <= 'd0  ;
              63: h_pin <= 'd0  ;
              default:  begin
                   h_pin <= 'd0;
                 end
            endcase

always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
         l_pin <= 'd0;
    else case (read_pin_id_add)
              0 : l_pin <= 'd63  ;   //'d0  ;
              1 : l_pin <= 'd62  ;   //'d1  ;
              2 : l_pin <= 'd61  ;   //'d2  ;
              3 : l_pin <= 'd60  ;   //'d3  ;
              4 : l_pin <= 'd59  ;   //'d4  ;
              5 : l_pin <= 'd58  ;   //'d5  ;
              6 : l_pin <= 'd57  ;   //'d6  ;
              7 : l_pin <= 'd56  ;   //'d7  ;
              8 : l_pin <= 'd55  ;   //'d8  ;
              9 : l_pin <= 'd54  ;   //'d9  ;
              10: l_pin <= 'd53  ;   //'d10 ;
              11: l_pin <= 'd52  ;   //'d11 ;
              12: l_pin <= 'd51  ;   //'d12 ;
              13: l_pin <= 'd50  ;   //'d13 ;
              14: l_pin <= 'd49  ;   //'d14 ;
              15: l_pin <= 'd48  ;   //'d15 ;
              16: l_pin <= 'd47  ;   //'d16 ;
              17: l_pin <= 'd46  ;   //'d17 ;
              18: l_pin <= 'd45  ;   //'d18 ;
              19: l_pin <= 'd44  ;   //'d19 ;
              20: l_pin <= 'd43  ;   //'d20 ;
              21: l_pin <= 'd42  ;   //'d21 ;
              22: l_pin <= 'd41  ;   //'d22 ;
              23: l_pin <= 'd40  ;   //'d23 ;
              24: l_pin <= 'd39  ;   //'d24 ;
              25: l_pin <= 'd38  ;   //'d25 ;
              26: l_pin <= 'd37  ;   //'d26 ;
              27: l_pin <= 'd36  ;   //'d27 ;
              28: l_pin <= 'd35  ;   //'d28 ;
              29: l_pin <= 'd34  ;   //'d29 ;
              30: l_pin <= 'd33  ;   //'d30 ;
              31: l_pin <= 'd32  ;   //'d31 ;
              32: l_pin <= 'd31  ;   //'d32  ;
              33: l_pin <= 'd30  ;   //'d33  ;
              34: l_pin <= 'd29  ;   //'d34  ;
              35: l_pin <= 'd28  ;   //'d35  ;
              36: l_pin <= 'd27  ;   //'d36  ;
              37: l_pin <= 'd26  ;   //'d37  ;
              38: l_pin <= 'd25  ;   //'d38  ;
              39: l_pin <= 'd24  ;   //'d39  ;
              40: l_pin <= 'd23  ;   //'d40  ;
              41: l_pin <= 'd22  ;   //'d41  ;
              42: l_pin <= 'd21  ;   //'d42  ;
              43: l_pin <= 'd20  ;   //'d43  ;
              44: l_pin <= 'd19  ;   //'d44  ;
              45: l_pin <= 'd18  ;   //'d45  ;
              46: l_pin <= 'd17  ;   //'d46  ;
              47: l_pin <= 'd16  ;   //'d47  ;
              48: l_pin <= 'd15  ;   //'d48  ;
              49: l_pin <= 'd14  ;   //'d49  ;
              50: l_pin <= 'd13  ;   //'d50  ;
              51: l_pin <= 'd12  ;   //'d51  ;
              52: l_pin <= 'd11  ;   //'d52  ;
              53: l_pin <= 'd10  ;   //'d53  ;
              54: l_pin <= 'd9   ;   //'d54  ;
              55: l_pin <= 'd8   ;   //'d55  ;
              56: l_pin <= 'd7   ;   //'d56  ;
              57: l_pin <= 'd6   ;   //'d57  ;
              58: l_pin <= 'd5   ;   //'d58  ;
              59: l_pin <= 'd4   ;   //'d59  ;
              60: l_pin <= 'd3   ;   //'d60  ;
              61: l_pin <= 'd2   ;   //'d61  ;
              62: l_pin <= 'd1   ;   //'d62  ;
              63: l_pin <= 'd0   ;   //'d63  ;
              default:  begin
                   l_pin <= 'd0 ;
                 end
            endcase
//每扫的位置
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n) begin
         h_scan <= 'd0;
    end
    else case (read_scan_id)
              0  : h_scan <= 'd0  ;
              1  : h_scan <= 'd1  ;
              2  : h_scan <= 'd2  ;
              3  : h_scan <= 'd3  ;
              4  : h_scan <= 'd4  ;
              5  : h_scan <= 'd5  ;
              6  : h_scan <= 'd6  ;
              7  : h_scan <= 'd7  ;
              default:  begin
                   h_scan <= 'd0;
                 end
            endcase
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
         l_scan <= 'd0;
    else case (read_scan_id)
              0  : l_scan <= 'd0 ;
              1  : l_scan <= 'd0;
              2  : l_scan <= 'd0 ;
              3  : l_scan <= 'd0 ;
              4  : l_scan <= 'd0 ;
              5  : l_scan <= 'd0 ;
              6  : l_scan <= 'd0 ;
              7  : l_scan <= 'd0 ;
              default:  begin
                   l_scan <= 'd0;
                 end
            endcase
//每port的位置
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n) begin
         h_port <= 'd0;
    end
    else case (read_port_id)
              0 : h_port <= 'd0   ;
              1 : h_port <= 'd0   ;
              default:  begin
                   h_port <= 'd0;
                 end
        endcase
 
always@(posedge I_sclk or negedge I_rst_n)
    if(!I_rst_n)
         l_port <= 'd0;
    else case (read_port_id)
              0 : l_port <= 'd0   ;
              1 : l_port <= 'd0   ;
              default:  begin
                   l_port <= 'd0;
                 end
        endcase            
//}}}++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
always@(posedge I_sclk )begin
    chip_id_tmp1<=read_chip_id             ;
    chip_id_tmp2<=chip_id_tmp1        ;
    chip_id_tmp3<=chip_id_tmp2        ;
    chip_id_tmp4<=chip_id_tmp3        ;
    chip_id_tmp5<=chip_id_tmp4        ;
end
always@(posedge I_sclk)begin
    port_id_tmp1 <= read_port_id;
    port_id_tmp2 <= port_id_tmp1;
    port_id_tmp3 <= port_id_tmp2;
    port_id_tmp4 <= port_id_tmp3;
    port_id_tmp5 <= port_id_tmp4;
end
endmodule

`default_nettype wire

// vim:set ts=4 sw=4 et fenc=utf-8 fdm=marker:
